#pragma once

#include <chrono>

//  always let ClockType = std::chrono::high_resolution_clock (can also be steady_clock/system_clock)
//  precision: nanoseconds
template<typename ClockType=std::chrono::high_resolution_clock> //  always use T = std::chrono::high_resolution_clock
class Timer {
    public:
        Timer(std::chrono::time_point<ClockType> tp = ClockType::now())
            : _start_time(tp) {};
        void Reset() { _start_time = ClockType::now(); }
        double Passed() const { return Passed<std::chrono::duration<double>>(); }
        double PassedSec() const { return Passed<std::chrono::duration<double>>(); }
        double PassedMilli() const { return Passed<std::chrono::duration<double, std::milli>>(); }
        double PassedMicro() const { return Passed<std::chrono::duration<double, std::micro>>(); }
        double PassedNano() const { return Passed<std::chrono::duration<double, std::nano>>(); }

    private:
        template<typename TimeType>
        double Passed() const {
            auto tp = ClockType::now();
            auto elapsed = std::chrono::duration_cast<TimeType>(tp - _start_time);
            return elapsed.count();
        }
        std::chrono::time_point<ClockType> _start_time;
};
